package com.tang.generate.service.impl

import com.tang.framework.core.domain.HttpResult
import com.tang.common.model.req.ReqId
import com.tang.generate.domain.GenField
import com.tang.generate.mapper.GenTableMapper
import com.tang.generate.model.req.TableAddReq
import com.tang.generate.model.req.TableFieldReq
import com.tang.generate.model.req.TableIndexReq
import com.tang.generate.service.IGenFieldService
import com.tang.generate.service.IGenService
import com.tang.generate.service.ITableService
import com.tang.generate.utils.TableConvert
import org.apache.commons.lang3.StringUtils
import org.springframework.beans.BeanUtils
import org.springframework.context.MessageSource
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.stream.Collectors
import jakarta.annotation.Resource

@Suppress("CAST_NEVER_SUCCEEDS")
@Service
open class TableServiceImpl : ITableService {

    @Resource
    private lateinit var genService: IGenService;

    @Resource
    private lateinit var genFieldService: IGenFieldService;

    @Resource
    private lateinit var jdbcTemplate: JdbcTemplate;

    @Resource
    private lateinit var messageSource: MessageSource;

    @Resource
    private lateinit var genTableMapper: GenTableMapper;

    @Transactional
    override fun add(tableAddReq: TableAddReq): HttpResult<String> {
        genService.save(tableAddReq);
        TableConvert.getCreateTableSql(tableAddReq).split(";").forEach {
            if (StringUtils.isNotBlank(it)){
                jdbcTemplate.execute(it);
            }
        }
        return HttpResult.ok();
    }


    @Transactional
    override fun update(tableAddReq: TableAddReq): HttpResult<String> {
        genService.save(tableAddReq)
        if (!tableAddReq.tableName.equals(tableAddReq.originTableName)) {
            jdbcTemplate.execute(TableConvert.getModifyTableName(tableAddReq.originTableName!!, tableAddReq.tableName!!))
        }
        TableConvert.getCreateTableFieldSql(tableAddReq.fieldList?.stream()?.filter {
            return@filter !it.originName.equals(it.name);
        }!!.collect(Collectors.toList()), tableAddReq.tableName!!, tableAddReq.databaseName!!)
                .forEach {
                    jdbcTemplate.execute(it);
                }
        TableConvert.getCreateTableIndexSql(tableAddReq.indexList!!, tableAddReq.tableName!!, tableAddReq.databaseName!!)
                .forEach {
                    jdbcTemplate.execute(it);
                }
        return HttpResult.ok();
    }

    override fun getTableInfo(reqId: ReqId): HttpResult<TableAddReq> {
        val genTable = genService.getById(reqId.id)
        val tableAddReq = TableAddReq(
                originTableName = genTable.tableName,
                tableName = genTable.tableName,
                className = genTable.className,
                databaseName = genTable.databaseName,
                desc = genTable.comment,
                charset = genTable.charset,
                charsetSort = genTable.charsetSort,
                autoIncrement = genTable.autoIncrement,
                engine = genTable.engine,
                fieldList = getFieldList(reqId.id!!),
                indexList = getIndexList(genTable.databaseName!!, genTable.tableName!!)
        )
        return HttpResult.ok(tableAddReq);
    }

    private fun getFieldList(tableId: Long): List<TableFieldReq> {
        return genFieldService.ktQuery().eq(GenField::tableId, tableId).list()
                .stream().map {
                    val tableFieldReq = TableFieldReq()
                    BeanUtils.copyProperties(it, tableFieldReq);
                    tableFieldReq.originName = it.name
                    tableFieldReq;
                }.collect(Collectors.toList());
    }

    private fun getIndexList(databaseName: String, tableName: String): List<TableIndexReq> {
        var tableIndexList: List<TableIndexReq> = listOf();
        genTableMapper.getTableIndex(databaseName, tableName).stream()
                .collect(Collectors.groupingBy { it["INDEX_NAME"] }).forEach { (key, value) ->
                    val tableIndexReq = TableIndexReq();
                    tableIndexReq.indexField = value.stream().map { it["COLUMN_NAME"]!! }.collect(Collectors.toList());
                    tableIndexReq.indexName = key;
                    tableIndexReq.indexMethod = if (value[0]["NON_UNIQUE"] as Long != 1L) "UNIQUE" else "NORMAL";
                    tableIndexReq.indexType = value[0]["INDEX_TYPE"]
                    tableIndexReq.desc = value[0]["INDEX_COMMENT"]
                    tableIndexList = tableIndexList.plus(tableIndexReq)
                }
        return tableIndexList;
    }
}
